import os
from random import random

import pyecharts.options as opts
from pyecharts.commons.utils import JsCode
from pyecharts.charts import Grid, Bar, Map, Pie, Line, Page, Timeline, Bar3D
import json

from pyecharts.globals import ThemeType


class pyCharts:
    def __init__(self):
        pass

    @staticmethod
    def generateEcharts(x_data, data, chart_title):
        print(f'正在生成 {chart_title} 折线图...')
        line = Line(init_opts=opts.InitOpts(width="850px", height="500px"))
        line.add_xaxis(x_data)
        for item in data:
            line.add_yaxis(
                series_name=item[0],
                y_axis=item[2:],
                label_opts=opts.LabelOpts(is_show=True),
            )

        line.set_global_opts(
            title_opts=opts.TitleOpts(title=chart_title),
            tooltip_opts=opts.TooltipOpts(trigger="axis"),
            yaxis_opts=opts.AxisOpts(
                type_="value",
                axistick_opts=opts.AxisTickOpts(is_show=True),
                splitline_opts=opts.SplitLineOpts(is_show=True),
            ),
            xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
        )
        return line

    @staticmethod
    def generateAndLayoutCharts(x_data, avg_data_per_city, max_data_per_city, min_data_per_city):

        year = avg_data_per_city[0][1]
        chart_generator = pyCharts()

        avg_line = chart_generator.generateEcharts(x_data, avg_data_per_city, f"各城市{year}年平均气温折线图")
        max_line = chart_generator.generateEcharts(x_data, max_data_per_city, f"各城市{year}年最高气温折线图")
        min_line = chart_generator.generateEcharts(x_data, min_data_per_city, f"各城市{year}年最低气温折线图")

        # 设置索引
        avg_line.chart_id = '88ba3942452f42559f1dcfdae2465f8f'
        max_line.chart_id = '2fdae38d2fdb4498899e2d7ab30c0449'
        min_line.chart_id = 'd7830c226dde478e857752ef2194e187'

        page = Page(layout=Page.DraggablePageLayout)
        page.add(avg_line, max_line, min_line)

        # 保存页面布局到 JSON 文件
        if not os.path.exists('charts'):
            os.makedirs('charts')
        page.render(f"charts\\各城市{year}年气温折线图.html")
        page.save_resize_html(source=f"charts\\各城市{year}年气温折线图.html",
                              cfg_file="charts\\chart_config.json",
                              dest=f"charts\\各省会城市{year}年气温分布折线图.html")

        # 移除临时文件
        os.remove(f"charts\\各城市{year}年气温折线图.html")
        return page

    # 中国十大幸福省份柱状图
    @staticmethod
    def generateARankedBarChart(happy_index_data):
        print('正在生成中国十大幸福省份柱状图...')

        sorted_data = sorted(happy_index_data.items(), key=lambda item: item[1], reverse=True)
        x_data = [item[0] for item in sorted_data][0:10]
        y_data = [item[1] for item in sorted_data][0:10]

        if not os.path.exists('charts'):
            os.makedirs('charts')

        bar = (
            Bar({"theme": ThemeType.DARK})
            .add_xaxis(x_data)
            .add_yaxis("幸福指数", y_data)
            .set_global_opts(
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
                title_opts=opts.TitleOpts(title="中国十大幸福省份"),
            )
            .render("charts\\中国十大幸福省份柱状图.html")
        )
        return bar

    @staticmethod
    def get_happy_index_chart(happy_index):
        data = []
        for (key, value) in happy_index.items():
            temp = [key, value]
            data.append(temp)

        happy_index = data
        happy_index = sorted(happy_index, key=lambda x: x[1], reverse=True)

        map_data = [[item[0], [int(item[1]), item[1], item[0]]] for item in happy_index]
        min_data, max_data = (
            min([d[1][0] for d in map_data]),
            max([d[1][0] for d in map_data]),
        )
        map_chart = (
            Map(init_opts=opts.InitOpts(width="2000px", height="1500px"))
            .add(
                series_name="幸福指数",
                data_pair=map_data,
                label_opts=opts.LabelOpts(is_show=False),
                is_map_symbol_show=False,
                itemstyle_opts={
                    "normal": {"areaColor": "#323c48", "borderColor": "#404a59"},
                    "emphasis": {
                        "label": {"show": True},
                        "areaColor": "rgba(255,255,255, 0.5)",
                    },
                },
            )
            .set_global_opts(
                title_opts=opts.TitleOpts(
                    title="中国各省幸福指数",
                    subtitle="幸福指数",
                    pos_left="left",
                    pos_top="top",
                    title_textstyle_opts=opts.TextStyleOpts(
                        font_size=25, color="rgba(255,255,255, 0.9)"
                    ),
                ),
                tooltip_opts=opts.TooltipOpts(
                    is_show=True,
                    formatter=JsCode(
                        """function(params) {
                        if ('value' in params.data) {
                            return params.data.value[2] + ': ' + params.data.value[1];
                        }
                    }"""
                    ),
                ),
                visualmap_opts=opts.VisualMapOpts(
                    is_calculable=True,
                    dimension=0,
                    pos_left="10",
                    pos_top="center",
                    range_text=["High", "Low"],
                    range_color=["lightskyblue", "yellow", "orangered"],
                    textstyle_opts=opts.TextStyleOpts(color="#ddd"),
                    min_=min_data,
                    max_=max_data,
                ),
            )
        )

        bar_x_data = [x[0] for x in map_data]

        bar_y_data = [{"name": x[0], "value": x[1][0]} for x in map_data]
        bar = (
            Bar()
            .add_xaxis(xaxis_data=bar_x_data[:10])  # 取排名前十的省份
            .add_yaxis(
                series_name="",
                yaxis_index=1,
                y_axis=bar_y_data[:10],  # 取排名前十的省份数据
                label_opts=opts.LabelOpts(
                    is_show=True, position="right", formatter="{b}: {c}"
                ),
            )
            .reversal_axis()
            .set_global_opts(
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(is_show=False)),
                yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(is_show=False)),
                tooltip_opts=opts.TooltipOpts(is_show=True),
                visualmap_opts=opts.VisualMapOpts(
                    is_calculable=True,
                    dimension=0,
                    pos_left="10",
                    pos_top="center",
                    range_text=["High", "Low"],
                    range_color=["lightskyblue", "yellow", "orangered"],
                    textstyle_opts=opts.TextStyleOpts(color="#ddd"),
                    min_=min_data,
                    max_=max_data,
                ),
                graphic_opts=[
                    opts.GraphicGroup(
                        graphic_item=opts.GraphicItem(
                            rotation=JsCode("Math.PI / 4"),
                            bounding="raw",
                            right=110,
                            bottom=110,
                            z=100,
                        ),
                        children=[
                            opts.GraphicRect(
                                graphic_item=opts.GraphicItem(
                                    left="center", top="center", z=100
                                ),
                                graphic_shape_opts=opts.GraphicShapeOpts(
                                    width=400, height=50
                                ),
                                graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
                                    fill="rgba(0,0,0,0.3)"
                                ),
                            ),
                            opts.GraphicText(
                                graphic_item=opts.GraphicItem(
                                    left="center", top="center", z=100
                                ),
                                graphic_textstyle_opts=opts.GraphicTextStyleOpts(
                                    text="幸福指数",
                                    font="bold 26px Microsoft YaHei",
                                    graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
                                        fill="#fff"
                                    ),
                                ),
                            ),
                        ],
                    )
                ],
            )
        )

        pie_data = [[item[0], item[1]] for item in sorted(happy_index, key=lambda x: x[1], reverse=True)[:10]]
        pie = (
            Pie()
            .add(
                series_name="",
                data_pair=pie_data,
                radius=["12%", "20%"],
                center=["75%", "85%"],
                itemstyle_opts=opts.ItemStyleOpts(
                    border_width=1, border_color="rgba(0,0,0,0.3)"
                ),
            )
            .set_global_opts(
                tooltip_opts=opts.TooltipOpts(is_show=True, formatter="{b} {d}%"),
                legend_opts=opts.LegendOpts(is_show=False),
            )
        )

        grid_chart = (
            Grid()
            .add(
                bar,
                grid_opts=opts.GridOpts(
                    pos_left="10", pos_right="45%", pos_top="70%", pos_bottom="5"
                ),
            )
            .add(pie, grid_opts=opts.GridOpts())
            .add(map_chart, grid_opts=opts.GridOpts())
        )

        return grid_chart

    # 中国个省份幸福指数
    @staticmethod
    def generate_happy_index_chart(happy_index_data):
        # Draw Timeline
        timeline = Timeline(
            init_opts=opts.InitOpts(width="1200px", height="800px", theme=ThemeType.DARK)
        )
        g = pyCharts().get_happy_index_chart(happy_index_data)
        timeline.add(g, time_point="幸福指数")

        timeline.add_schema(
            orient="vertical",
            is_auto_play=True,
            is_inverse=True,
            play_interval=5000,
            pos_left="null",
            pos_right="5",
            pos_top="20",
            pos_bottom="20",
            width="50",
            label_opts=opts.LabelOpts(is_show=True, color="#fff"),
        )

        if not os.path.exists('charts'):
            os.makedirs('charts')
        timeline.render("charts\\中国各省份幸福指数.html")

    # 未来 15 天天气评分
    @staticmethod
    def get_future_weather_chart(weather_data):

        # 对每一行求平均值
        city_score = weather_data.mean(axis=1)
        city_score = city_score.sort_values(ascending=False)  # 排序

        x_data = city_score.index.tolist()[:10]
        y_data = city_score.values.tolist()[:10]

        if not os.path.exists('charts'):
            os.makedirs('charts')

        # 绘制柱状图
        c = (
            Bar({"theme": ThemeType.DARK})
            .add_xaxis(x_data)
            .add_yaxis("推荐指数", y_data)
            .set_global_opts(
                title_opts={"text": "未来几日旅游推荐城市"}
            )
            .render("charts\\未来几日旅游推荐城市.html")
        )
